<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
  <title>动态粉色星点爱心</title>
  <style>
    body {
      margin: 0;
      background: black;
      overflow: hidden;
    }
    canvas {
      display: block;
    }
  </style>
</head>
<body>
  <canvas id="heartCanvas"></canvas>
  <script>
    const canvas = document.getElementById("heartCanvas");
    const ctx = canvas.getContext("2d");
    resize();
    window.onresize = resize;

    function resize() {
      canvas.width = window.innerWidth;
      canvas.height = window.innerHeight;
    }

    // ========== 绘制小爱心 ==========
    function drawMiniHeart(ctx, x, y, size, color, alpha) {
      ctx.save();
      ctx.translate(x, y);
      ctx.scale(size, size);
      ctx.beginPath();
      ctx.moveTo(0, -2);
      ctx.bezierCurveTo(2, -4, 4, -2, 0, 2);
      ctx.bezierCurveTo(-4, -2, -2, -4, 0, -2);
      ctx.closePath();
      ctx.fillStyle = `rgba(${color[0]}, ${color[1]}, ${color[2]}, ${alpha})`;
      ctx.fill();
      ctx.restore();
    }

    // ========== 背景飘落小爱心 ==========
    class BgHeart {
      constructor() { this.reset(); }
      reset() {
        this.x = Math.random() * canvas.width;
        this.y = Math.random() * canvas.height;
        this.size = Math.random() * 1 + 0.8;
        this.alpha = Math.random();
        this.speed = Math.random() * 0.4 + 0.2;
      }
      update() {
        this.y += this.speed;
        if (this.y > canvas.height) {
          this.x = Math.random() * canvas.width;
          this.y = -10;
        }
      }
      draw() {
        drawMiniHeart(ctx, this.x, this.y, this.size, [255,182,193], this.alpha);
      }
    }
    let bgHearts = Array.from({ length: 250 }, () => new BgHeart());

    // ========== 爱心函数 ==========
    function heartFunction(t, scale = 12) {
      let x = 16 * Math.pow(Math.sin(t), 3);
      let y = 13 * Math.cos(t) - 5 * Math.cos(2 * t) - 2 * Math.cos(3 * t) - Math.cos(4 * t);
      return [x * scale, -y * scale];
    }

    // ========== 爱心粒子（附带文字） ==========
    class HeartParticle {
      constructor(texts) {
        this.texts = texts;
        this.reset();
      }
      reset() {
        let t = Math.random() * Math.PI * 2;
        let [hx, hy] = heartFunction(t, canvas.width / 70);
        this.x = canvas.width / 2;
        this.y = canvas.height / 2;
        this.targetX = canvas.width / 2 + hx + (Math.random() - 0.5) * 40;
        this.targetY = canvas.height / 2 + hy + (Math.random() - 0.5) * 40;
        this.size = Math.random() * 3.5 + 3.5;
        this.alpha = 0;
        this.progress = 0;
        this.speed = Math.random() * 0.005 + 0.002; // ⭐ 慢速
        // 10% 的概率绑定文字
        this.text = Math.random() < 0.04 ? this.texts[Math.floor(Math.random()*this.texts.length)] : null;
        this.fontSize = 36 + Math.random()*15;
      }
      update() {
        this.progress += this.speed;
        if (this.progress >= 1) this.reset();
        this.x += (this.targetX - this.x) * 0.04;
        this.y += (this.targetY - this.y) * 0.04;
        this.alpha = Math.min(1, this.progress * 2);
      }
      draw() {
        if (this.text) {
          ctx.font = `${this.fontSize}px Arial`;
          ctx.fillStyle = `rgba(255,182,193,${this.alpha})`;
          ctx.textAlign = "center";
          ctx.fillText(this.text, this.x, this.y);
        } else {
          drawMiniHeart(ctx, this.x, this.y, this.size, [255,105,180], this.alpha);
        }
      }
    }

    let texts = ["QXH"];
    let heartParticles = Array.from({ length: 4000 }, () => new HeartParticle(texts)); // ⭐ 数量翻三倍

    // ========== 动画 ==========
    function animate() {
      ctx.clearRect(0, 0, canvas.width, canvas.height);
      bgHearts.forEach(h => { h.update(); h.draw(); });
      heartParticles.forEach(p => { p.update(); p.draw(); });
      requestAnimationFrame(animate);
    }
    animate();
  </script>
</body>
</html>